﻿#include "pcrState.h"

void PCRState::init(){

    DebugLog::funcStart(DEBUG_CONTEXT);

    canAnalysis = true;


    try {
        // 初始化数据库连接
        QSqlDatabase db = dbHelper::openConnection();
        QSqlQuery query(db);
        QString sql;



        // 实验名称
        sql="SELECT ExperimentName,RunTime,FinishTime FROM ExperimentInfo";

        query.exec(sql);
        while (query.next()) {
            experimentName = query.value("ExperimentName").toString();
            experimentRunTime = query.value("RunTime").toString();
            experimentFinishTime = query.value("FinishTime").toString();
        }



        // 内标
        sql="Select Name  From ItemCode where IsDefault=1 and DicCode=11";
        query.exec(sql);
        while (query.next()) {
            modelIR = query.value("Name").toString();
        }

        curPage = PCRState::RAW;
        curChart = PCRState::DELTA_RN;
        showThr = false;

        modelFunc = 0;
        modelFilter = 0;
        modelCt = 0;



        // 对接AccessInfo数据
        QSet<QString> SampleIds;
        sql = "select * from SampleAccessInfo";
        query.exec(sql);
        while(query.next()){
            SampleIds.insert(query.value("SampleGuid").toString());
        }

        // 数据读取 - 每个孔位的样本信息
        sql = "select * from sampleInfo";
        query.exec(sql);
        nameList.clear();
        typeList.clear();
        posiList.clear();
        while(query.next()){
            QString ID = query.value("ID").toString();
            if(SampleIds.size()>0){     // 适配没有AccessInfo数据的情况
                if(! SampleIds.contains(ID)){
                    continue;
                }
            }
            sampleInfo[ID] = QVector<QString>();
            QString posi_name = QString((query.value("RowNum").toInt())+'A') + QString::number(query.value("ColNum").toInt()+1);


            sampleInfo[ID].append(posi_name);
            sampleInfo[ID].append(query.value("SampleName").toString());
            sampleInfo[ID].append(query.value("SampleType").toString());
            sampleInfo[ID].append(query.value("SampleConc").toString());

            sampleInfo_posi[posi_name] = QVector<QString>();
            sampleInfo_posi[posi_name].append(posi_name);
            sampleInfo_posi[posi_name].append(query.value("SampleName").toString());
            sampleInfo_posi[posi_name].append(query.value("SampleType").toString());
            sampleInfo_posi[posi_name].append(query.value("SampleConc").toString());

            if(!posiList.contains(posi_name)){
                posiList.append(posi_name);
            }if(!nameList.contains(query.value("SampleName").toString())){
                nameList.append(query.value("SampleName").toString());
            }if(!typeList.contains(query.value("SampleType").toString())){
                typeList.append(query.value("SampleType").toString());
            }
        }
        std::sort(posiList.begin(), posiList.end());
        std::sort(nameList.begin(), nameList.end());
        std::sort(typeList.begin(), typeList.end());
        channelList.clear();
        channelList.append("FAM");
        channelList.append("VIC");
        channelList.append("ROX");
        channelList.append("CY5");

        foreach(ChannelName channel, channelList){
            modelRange_start[channel] = 3;
            modelRange_end[channel] = 15;
        }

        posiList_filter = posiList;
        nameList_filter = nameList;
        typeList_filter = typeList;
        channelList_filter = channelList;

        // ...这个CurveList是干嘛的.....
//        foreach(PosiName posi, posiList){
//            foreach(ChannelName channel, channelList){
//                curveList.push_back(CurveName(channel, posi));
//            }
//        }

        sql = "Select AccessName, Pos FROM SampleAccessInfo inner join SampleInfo on SampleInfo.ID = SampleAccessInfo.SampleGuid";
        query.exec(sql);
        while(query.next()){
            curveList.push_back(query.value("AccessName").toString() + "_" + ((query.value("Pos").toInt()-1)%8+'A') + QString::number((query.value("Pos").toInt()-1)/8+1));
        }


        // 数据读取 - 荧光数据
        rawData.clear();
        for(auto iter = sampleInfo.begin(); iter != sampleInfo.end(); iter ++){

            QString sampleId = iter.key();
            QString  sql=QString("select f.SampleId,FAM,ROX,CY5,VIC "
                                 "From FluorescenceData f "
                                 "where SampleId='%1' "
                                 "order by CyclesNumber;").arg(sampleId);

            query.exec(sql);
            QVector<QPointF> fData;
            QVector<QPointF> rData;
            QVector<QPointF> cData;
            QVector<QPointF> vData;
            int a = 1;
            QString posi_name;
            while (query.next()) {

                QString sampleid = query.value("SampleId").toString();
                posi_name = sampleInfo[sampleid][0];

                QPointF fpoint=QPoint(a,query.value("FAM").toDouble());
                fData.append(fpoint);
                QPointF rpoint=QPoint(a,query.value("ROX").toDouble());
                rData.append(rpoint);
                QPointF cpoint=QPoint(a,query.value("CY5").toDouble());
                cData.append(cpoint);
                QPointF vpoint=QPoint(a,query.value("VIC").toDouble());
                vData.append(vpoint);
                a ++;
            }
            if(!fData.isEmpty()) rawData["FAM_"+posi_name] = fData;
            if(!vData.isEmpty()) rawData["VIC_"+posi_name] = vData;
            if(!rData.isEmpty()) rawData["ROX_"+posi_name] = rData;
            if(!cData.isEmpty()) rawData["CY5_"+posi_name] = cData;
        }

        // 初始化每个通道的阈值
        thrList["FAM"] = 0;
        thrList["VIC"] = 0;
        thrList["ROX"] = 0;
        thrList["CY5"] = 0;
        thrList_log["FAM"] = 0;
        thrList_log["VIC"] = 0;
        thrList_log["ROX"] = 0;
        thrList_log["CY5"] = 0;
        thrList_diff["FAM"] = 0;
        thrList_diff["VIC"] = 0;
        thrList_diff["ROX"] = 0;
        thrList_diff["CY5"] = 0;

        if(rawData.size()>0 && rawData.begin()->size()>0){
            cycleNum = ((rawData.begin()).value()).back().x();  // 更新循环数
        }else{
//            qDebug() << "PCRStateCalculator line150 数据错误：RawData为空";
//            DebugLog::write("PCRStateCalculator line150 数据错误：RawData为空");
            canAnalysis = false;
        }

        cycleNum_ampl = cycleNum;
        sql = "select max(CycleNum) as AmplCycleNum from AmplStepTemp";
        query.exec(sql);
        while(query.next()){
            cycleNum_ampl = std::max( query.value("AmplCycleNum").toDouble(), cycleNum );
        }


        // 初始化Model
        foreach(PosiName posi, posiList){
            foreach(ChannelName channel, channelList){
                CurveName name(channel, posi);
                modelList[name] = new QPCRModel::Model();
                if(rawData.contains(name)){
                    modelList[name]->setRawData(rawData[name]);
                }else{
//                    qDebug() << "PCRStateCalcular line167 数据错误：" << posi << "RawData为空";
//                    DebugLog::write("PCRStateCalculator line167 数据错误：RawData为空");
                    canAnalysis = false;
                }
            }
        }
        if(canAnalysis == false){
            qDebug() << "PCRStateCalcular line184 数据错误：" << "RawData为空";
            DebugLog::write("PCRStateCalculator line184 数据错误：RawData为空 ---->");
        }

    } catch (...) {
        QMessageBox msg;
        msg.setText("数据分析初始化异常");
        msg.exec();
        qDebug() << __FUNCTION__ << "初始化异常";
        exit(1);
    }

    calModel();
    calCt();
    calStandardCurve();


    DebugLog::funcEnd(DEBUG_CONTEXT);

}

void PCRState::calModel(){

    DebugLog::funcStart(DEBUG_CONTEXT);


    rawData_filter.clear();
    for(auto iter = modelList.begin(); iter != modelList.end(); iter ++){

        if(modelFilter >= 0){               // 我怎么把filter_data写到Model里了
            rawData_filter[iter.key()] = QPCRModel::Model::filter(rawData[iter.key()]);
        }else{
            rawData_filter[iter.key()] = rawData[iter.key()];
        }


        if(! canAnalysis){
//            DebugLog::funcEnd(DEBUG_CONTEXT, "Cannot Analysis");
            continue;
        }

        QPCRModel::Model* model = iter.value();
        model->setParam(QPCRModel::Model::FUNC_TYPE, modelFunc);
        model->startCalculation();
        // 内标值更新
        if(iter.key().channel() == modelIR){
            rangeIR[iter.key().posi()] = model->getTopValue() - model->getBgValue();
        }
    }
    foreach(ChannelName channel, channelList){
        thrList[channel] = 0;
        thrList_log[channel] = 0;
        thrList_diff[channel] = 0;
        thrList_Rn[channel] = 0;
        thrList_logRn[channel] = 0;
    }


    if(! canAnalysis){
        DebugLog::funcEnd(DEBUG_CONTEXT, "Cannot Analysis");
        return;
    }

    if(modelCt < 0){
        for(auto iter = modelList.begin(); iter != modelList.end(); iter ++){
            QPCRModel::Model* model = iter.value();
            CurveName curveName = iter.key();

            int endRange = modelAutoThr ? 15 : modelRange_end[curveName.channel()]; // 是否自动基线

            for(auto thr = thrList.begin(); thr != thrList.end(); thr ++){
                if(iter.key().contains(thr.key())){
                    thr.value() = std::max(thr.value(), model->getThreshold(endRange, QPCRModel::Model::DELTA_RN));
                }
            }
            for(auto thr = thrList_log.begin(); thr != thrList_log.end(); thr ++){
                if(iter.key().contains(thr.key())){
                    thr.value() = std::max(thr.value(), model->getThreshold(endRange, QPCRModel::Model::LOG_DELTA_RN));
                }
            }
            for(auto thr = thrList_Rn.begin(); thr != thrList_Rn.end(); thr ++){
                if(iter.key().contains(thr.key())){
                    thr.value() = std::max(thr.value(), model->getThreshold(endRange, QPCRModel::Model::RN));
                }
            }
            for(auto thr = thrList_logRn.begin(); thr != thrList_logRn.end(); thr ++){
                if(iter.key().contains(thr.key())){
                    thr.value() = std::max(thr.value(), model->getThreshold(endRange, QPCRModel::Model::LOG_RN));
                }
            }
            for(auto thr = thrList_diff.begin(); thr != thrList_diff.end(); thr ++){
                if(iter.key().contains(thr.key())){
                    if(rangeIR[iter.key().posi()] != 0){
                        thr.value() = std::max(thr.value(), model->getThreshold(QPCRModel::Model::DELTA_RN) / rangeIR[iter.key().posi()]);
                    }
                }
            }
        }
    }else{
        showThr = false;
    }

    DebugLog::funcEnd(DEBUG_CONTEXT);
}

void PCRState::calCt(){

    DebugLog::funcStart(DEBUG_CONTEXT);
    if(! canAnalysis){
        DebugLog::funcEnd(DEBUG_CONTEXT, "Cannot Analysis");
        return;
    }


    if(modelCt >= 0){    // 1. 相对阈值
        for(auto iter = modelList.begin(); iter != modelList.end(); iter ++){
            Ct[iter.key()] = iter.value()->getCt_relative(modelCt);

        }
    }else{         // 2. 绝对阈值：根据阈值线更新Ct
        for(auto iter = modelList.begin(); iter != modelList.end(); iter ++){
            ChannelName channel = iter.key().channel();
            PosiName    posi    = iter.key().posi();
            double threshold;
            if(curChart == PCRState::NORM){             // RN
                threshold = thrList_diff[channel] * rangeIR[posi];
                Ct[iter.key()] = iter.value()->getCt(threshold, QPCRModel::Model::DELTA_RN);
            }else if(curChart == PCRState::LOG_DELTA_RN || curChart == PCRState::DELTA_RN){     // DELTA_RN / DELTA_RN
                threshold = thrList[channel];
                Ct[iter.key()] = iter.value()->getCt(threshold, QPCRModel::Model::DELTA_RN);
            }else{          // LOG_RN / LOG_DELTA_RN
                threshold = thrList_Rn[channel];
                Ct[iter.key()] = iter.value()->getCt(threshold, QPCRModel::Model::RN);
            }
        }
    }

    // 平均Ct值计算
    foreach(ChannelName channel, channelList){
        avgCt[channel] = 0;
        double ctNum = 0;
        foreach(PosiName posi, posiList){
            CurveName curve(channel, posi);
            if(Ct[curve] != 0 || !std::isinf(Ct[curve])){
                avgCt[channel] += Ct[curve];
                ctNum ++;
            }
        }
        avgCt[channel] /= ctNum;
    }
    DebugLog::funcEnd(DEBUG_CONTEXT);

}

void PCRState::calStandardCurve(){


    DebugLog::funcStart(DEBUG_CONTEXT);
    if(! canAnalysis){
        DebugLog::funcEnd(DEBUG_CONTEXT, "Cannot Analysis");
        return;
    }


    QSet<QString> standardPosiList;
    for(auto sample = sampleInfo.begin(); sample != sampleInfo.end(); sample ++){
        if(sample.value()[2].contains("标准")){
            standardPosiList.insert(sample.value()[0]);
        }
    }

    // 计算每个通道的返回结果
    standardLine.clear();
    for(auto channel = channelList.begin(); channel != channelList.end(); channel ++){

        QVector<QPointF> pointList;
        // x: log10(浓度)  y: Ct
        for(auto posi = standardPosiList.begin(); posi != standardPosiList.end(); posi ++){
            QString name = (*channel) + '_' + (*posi);
            if(!modelList.contains(name)){
                qDebug() << "PCRStateCalculator line309 出错 模型不存在" << name;
                continue;
            }
            double Ct;
//            if(modelCt < 0 || modelIR==*channel){ // 绝对阈值和内标的情况下，阈值使用Rn算
            if(modelCt < 0){            // 我忘了这块内标为什么要用Rn了……
                double threshold;
                if(curChart==PCRState::NORM){
                    threshold = thrList_diff[*channel] * rangeIR[*posi];
                    Ct = modelList[name]->getCt(threshold, QPCRModel::Model::DELTA_RN);
                }else if(curChart==PCRState::LOG_RN || curChart == PCRState::RN){
                    threshold = thrList_Rn[*channel];
                    Ct = modelList[name]->getCt(threshold, QPCRModel::Model::RN);
                }else{
                    threshold = thrList[*channel];
                    Ct = modelList[name]->getCt(threshold, QPCRModel::Model::DELTA_RN);
                }
            }else{
                Ct = modelList[name]->getCt_relative(modelCt);
            }
            double Conc = sampleInfo_posi[*posi][3].toDouble();
            if(Ct != 0){
                pointList.append(QPointF(log10(Conc), Ct));
            }
        }
        double k, b;

        QPCRModel::Model::linearFitting(pointList, &k, &b);


        standardLine[*channel] = QVector<double>();
        standardLine[*channel].append(k);
        standardLine[*channel].append(b);

        E[*channel] = pow(10, -1.0/k);
        R2[*channel] = pow(QPCRModel::Model::calCoeff(pointList), 2);

    }

    // 每条曲线的浓度 + 平均浓度
    concList.clear();
    avgConcList.clear();
    for(auto channel = channelList.begin(); channel != channelList.end(); channel ++){
        double k = standardLine[*channel][0];
        double b = standardLine[*channel][1];

        double num = 0;
        avgConcList[*channel] = 0;
        for(auto sample = sampleInfo_posi.begin(); sample != sampleInfo_posi.end(); sample++){
            QString name = (*channel) + '_' + sample.key();
            double Ct;
//            if(modelCt < 0 || modelIR==*channel){
            if(modelCt < 0){                // 我忘了这块为什么内标要用Rn了……
                double threshold;
                if(curChart==PCRState::NORM){
                    threshold = thrList_diff[*channel] * rangeIR[sample.key()];
                    Ct = modelList[name]->getCt(threshold, QPCRModel::Model::DELTA_RN);
                }else if(curChart==PCRState::RN || curChart==PCRState::LOG_RN){
                    threshold = thrList_Rn[*channel];
                    Ct = modelList[name]->getCt(threshold, QPCRModel::Model::RN);
                }else{
                    threshold = thrList[*channel];
                    Ct = modelList[name]->getCt(threshold, QPCRModel::Model::DELTA_RN);
                }
            }else{
                Ct = modelList[name]->getCt_relative(modelCt);
            }
            if(sample.value()[2].contains("标准")){
                // 标准品的浓度
                concList[name] = sample.value()[3].toDouble();
                standardPoint[name] = QPointF(log10(sample.value()[3].toDouble()), Ct);
            }else if(*channel == modelIR){
                concList[name] = 0;
                standardPoint[name] = QPointF(0, 0);
            } else if(Ct > 0){
                concList[name] = pow(10, (Ct - b) / k);
                avgConcList[*channel] += concList[name];
                standardPoint[name] = QPointF((Ct-b)/k, Ct);
                num ++;
            }else{
                concList[name] = 0;
                standardPoint[name] = QPointF(0, 0);
            }

        }
        if(num == 0){
            avgConcList[*channel];
        }else{
            avgConcList[*channel] /= num;
        }
    }
    DebugLog::funcEnd(DEBUG_CONTEXT);

}


